# coding=utf8
import os


class Preliminary:

    """
    表4-1 open函数文件打开方式说明
    打开模式	功能描述
    r/rb	只读文本方式/只读二进制方式。
    w/wb	只写文本方式/只写二进制方式。
            每次打开文件从头写入内容，如文件已经存在，则原内容会被清除。若文件不存在，则创建新文件。
    a/ab	追加文本方式/追加二进制方式。
            若文件已存在，则将文件指针定位于文件结尾，追加内容被写入原有内容之后。
            若文件不存在，则创建新文件从头开始写入。
    r+/rb+	读+文本方式/读+二进制方式。
            既可以从头读取文件内容，也可以从开头向文件中写入新的内容，写入的新内容会覆盖文件中等长度的原有内容。
    w+/wb+	写+文本方式/写+二进制方式。
            若文件已存在，则打开文件，并从头写入内容，原内容被覆盖。
            若不存在，则创建新文件
    a+/ab+	添加+文本方式/添加+二进制方式。
            若文件已存在，则将文件指针定位于文件结尾，追加的内容将被写入原有内容之后；
            若文件不存在，则创建新文件进行写入
    """

    @staticmethod
    def demo_open():
        """
        fobj = open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
        参数说明:
        file:字符串，字节串，或整数。字符串或字节串表示要打开的文件名称，包括文件所在路径。整数表示一个文件对象的标识符。
            如果使用整数标识符，注意与closefd的配合使用。
        mode:字符串。文件打开方式。
        buffering:整数。打开文件的缓冲方式。buffering为0时表示不缓冲，为1时表示只缓冲一行数据，为-1时表示使用系统默认缓冲机制，默认为-1。
            任何大于1的值表示使用给定的的值作为缓冲区大小。
            注：缓冲是指用于读取文件的缓冲区，缓冲区就是一段内存区域。设置缓冲区的目的是先把文件内容读取到缓冲区，可以减少CPU读取磁盘的次数。
        encoding:字符串，或None。文件编码方式，即以哪种编码读写文本文件。使用缺省值None时，采用“utf-8”编码。
        errors:字符串，或None。可选参数。如何处理编解码错误。设置为None或”strict”时，遇到编解码错误，触发异常ValueError。
            如果设置为“ignore”时，忽略编解码处理过程中的错误。
        newline:字符串，或None。文本文件行结束字符。字符串可以取值：{ ''、 '\\n'、 '\\r'、'\\r\\n'}。
            在读取模式时，若newline=None，则作为通用换行符模式工作，即遇到\\n，\\r或\\r\\n都可以作为换行标识，并且统一转换为\\n作为文本输入
            的换行符。若newline=’’，也是通用换行符模式工作，但不作转换。当设置为其它相应字符时，就会判断到相应的字符作为换行符，并保持原样
            输入到文本。
            在写入模式时，若newline=None，那么所有输出文本都是采用\\n作为换行符。若newline=’’或\\n，不作任何替换动作。如果是其它字符，
            会在字符后面添加\\n作为换行符。
        closefd: 布尔值。用于控制文件关闭状态。若file参数为传入一个文件句柄，当closefd=False时，表示退出时不关闭文件句柄，
            当closefd=True时，表示退出时关闭文件句柄。若file设置的是文件名，closefd必须设置为True。
        opener:可调用对象。该对象返回一个文件标识符，用来实现自己定义打开文件方式。
        返回值：
        fobj：文件对象。用于对文件进行操作。
        """
        base_dir = os.path.dirname(os.path.abspath(__file__))
        text_file = os.path.join(base_dir, 'text41.txt')

        # 直接使用open以文本方式打开文件，读取文件所有文本内容
        fobj = open(text_file, 'r', encoding='utf8')
        t = fobj.read()
        print(t)

    @staticmethod
    def demo_file_object():
        """
        展示文件对象的使用，以文件对象的三方法读取文本文件内容：
        read方法：按照数量限制读取字符
        readline方法：按照字符数量限制，读取一行
        readlines方法：按照字符数量限制，读取多行
        """
        base_dir = os.path.dirname(os.path.abspath(__file__))
        text_file = os.path.join(base_dir, 'text41.txt')

        # use with statement to open file
        with open('text41.txt', 'r', encoding='utf8') as fobj:
            read_text = fobj.read()
            print(type(read_text))
            print(read_text)

        # 使用read(size=-1)读取所有文件内容
        # 参数size为整数，限定读取的字符数。读取的字符计数时包括换行符。
        # 如果size为正整数，从文件中读取最多size个字符。当size大于文件内存储的字符数时，读取到文件结束符停止读取，返回所读取的字符串。
        # 如果size为-1或任意负数，则读取所有文件内容。
        with open(text_file, mode='r+', encoding='utf8') as fobj:
            print("---read(20):读取20个字符---")
            t = fobj.read(20)
            print(t)

        # 使用readline(size=-1)读取一行内容
        # 参数size为整数，限定一行内读取的字符数。
        # 如果size大于当前行中的字符数，则读取到行结束停止读取。
        # 如果设置为-1或任意负数，则读取当前行内容。
        with open(text_file, mode='r+', encoding='utf8') as fobj:
            print("---readline(50):读取当前行50个字符")
            t = fobj.readline(50)
            print(t)

        # 使用readlines(hint=-1)读取多行内容
        # hint为0或负数时，读取所有行内容，
        # hint为正数时，为读取行中字符数的限定值。
        #
        with open(text_file, mode='r+', encoding='utf8') as fobj:
            print("---readlines(12):读取1行字符：每行字符12个，超过12读取2行")
            lines = fobj.readlines(12)
            print(lines)
            print("---读取2行字符：每行字符12个，第一行12+换行符+第二行12=25，超过25读取3行")
            lines = fobj.readlines(25)
            print(lines)
            fobj.seek(0)
            print("---读取所有行字符")
            lines = fobj.readlines(-2)
            print(lines)
            print("---直接迭代文件对象，读取所有行字符")
            fobj.seek(0)
            for line in fobj:
                print(line, end='')


def task():
    base_dir = os.path.dirname(os.path.abspath(__file__))
    text_file = os.path.join(base_dir, 'text41.txt')
    fobj = open(text_file, 'r', encoding='utf8')
    read_text = fobj.read()
    print(read_text)
    fobj.close()


def expand_1():
    """
    以写方式打开文件text41b.txt、text41c.txt，写入6行字符串
    """

    base_dir = os.path.dirname(os.path.abspath(__file__))

    text_file = os.path.join(base_dir, 'text41b.txt')
    fobj = open(text_file, 'w', encoding='utf8')
    for i in range(1, 7):
        fobj.write("文本文件第{}行\n".format(i))
    fobj.close()

    text_file2 = os.path.join(base_dir, 'text41c.txt')
    fobj = open(text_file2, 'w', encoding='utf8')
    write_lines = ["文本文件第{}行\n".format(i) for i in range(1, 7)]
    fobj.writelines(write_lines)
    fobj.close()


def expand_2():
    """
    以读方式打开文本文件，从第2行开始，读取3行文本
    """
    base_dir = os.path.dirname(os.path.abspath(__file__))
    text_file = os.path.join(base_dir, 'text41b.txt')

    start_line = 2
    read_line_num = 3
    read_lines = []
    with open(text_file, 'r', encoding='utf8') as fobj:
        for lno, line in enumerate(fobj.readlines()):
            if lno < start_line:
                continue
            read_lines.append(line)
            if len(read_lines) == read_line_num:
                break
    print(read_lines)


if __name__ == '__main__':
    # Preliminary.demo_open()
    Preliminary.demo_file_object()
    # expand_1()
    # expand_2()
